package com.lcy.struct.bTreePlus.disk.recovery.undo;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @author lucongyang
 * @date Created in  15:44
 * @description
 */
class DoUndo {
    private DoUndo() {
    }

    static DoUndo getInstance() {
        return Singleton.INSTANCE;
    }

    List<Long> doUndo(LinkedHashMap<Long, List<String>> map) {
        List<Long> successList = new ArrayList<>();
        List<Map.Entry<Long, List<String>>> list = new ArrayList<>(map.entrySet());
        for (int i = list.size() - 1; i >= 0; i--) {
            Map.Entry<Long, List<String>> m = list.get(i);
            if (doUndo(m.getValue())) {
                successList.add(m.getKey());
            }
        }
        return successList;
    }

    boolean doUndo(List<String> undoStrList) {
        if (undoStrList == null) {
            return false;
        }
        boolean result = true;
        List<String> addList = new ArrayList<>();
        List<String> updateList = new ArrayList<>();
        List<String> delList = new ArrayList<>();
        for (int i = undoStrList.size() - 1; i >= 0; i--) {
            String undoStr = undoStrList.get(i);
            if (UndoAdd.getInstance().isSuit().suitable(undoStr)) {
                addList.add(undoStr);

                if (!updateList.isEmpty()) {
                    UndoUpdate.getInstance().doUndo(updateList);
                    updateList = new ArrayList<>();
                }
                if (!delList.isEmpty()) {
                    UndoDel.getInstance().doUndo(delList);
                    delList = new ArrayList<>();
                }
            } else if (UndoUpdate.getInstance().isSuit().suitable(undoStr)) {
                updateList.add(undoStr);

                if (!addList.isEmpty()) {
                    UndoAdd.getInstance().doUndo(addList);
                    addList = new ArrayList<>();
                }
                if (!delList.isEmpty()) {
                    UndoDel.getInstance().doUndo(delList);
                    delList = new ArrayList<>();
                }
            } else if (UndoDel.getInstance().isSuit().suitable(undoStr)) {
                delList.add(undoStr);

                if (!addList.isEmpty()) {
                    UndoAdd.getInstance().doUndo(addList);
                    addList = new ArrayList<>();
                }
                if (!updateList.isEmpty()) {
                    UndoUpdate.getInstance().doUndo(updateList);
                    updateList = new ArrayList<>();
                }
            } else {
                result = false;
            }
        }

        UndoAdd.getInstance().doUndo(addList);
        UndoUpdate.getInstance().doUndo(updateList);
        UndoDel.getInstance().doUndo(delList);
        return result;
    }

    interface Suitable {
        boolean suitable(String undoStr);
    }

    private static class Singleton {
        private static final DoUndo INSTANCE = new DoUndo();
    }
}
